<?php
/** */
namespace app\api\service;

use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User as UserModel;
use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;

class UserToken extends Token{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    //获取完整（拼接）的$wxLoginUrl
    function __construct($code){
        $this->code=$code;
        $this->wxAppID=config('wx.app_id');
        $this->wxAppSecret=config('wx.app_secret');
        $this->wxLoginUrl=sprintf(config('wx.login_url'),
            $this->wxAppID,$this->wxAppSecret,$this->code);
    }

    public function get(){
       $result=curl_get($this->wxLoginUrl);
        $wxResult=json_decode($result,true);
        if(empty($wxResult)){
            throw new Exception('获取session_key及openID时异常，微信内部错误'); 
        }else{
            $loginFail=array_key_exists('errcode',$wxResult);
            if($loginFail){
                $this->processLoginError($wxResult);
            }else{
                return $this->grantToken($wxResult);
            }
        }
    }

    //授权令牌
    private function grantToken($wxResult){
        //拿到openid
        //查看数据库，该openid是否存在
        //如果存在则不处理，否则新增一条user记录
        //生产令牌，准备缓存数据，写入缓存
        //把令牌返回到客户端去
        //key:令牌
        //value:wxResult,uid,scope
        $openid=$wxResult['openid'];
        $user=UserModel::getByOpenID($openid);
        if($user){
            $uid=$user->id;
        }
        else{
            $uid=$this->newUser($openid);
        }
        $cachedValue=$this->prepareCachedValue($wxResult,$uid);
        $token=$this->saveTokenCache($cachedValue);
        return $token;
    }

    //写入缓存
    private function saveTokenCache($cachedValue){
        $key=self::generateToken();
        $value=json_encode($cachedValue);
        $expire_in=config('setting.token_expire_in');

        $request=cache($key,$value,$expire_in);
        if(!$request){
            throw new TokenException([
                'msg'=>'服务器缓存异常',
                'errorCode'=>10005
            ]);
        }
        return $key;
    }

    //准备Value的一系列数据
    private function prepareCachedValue($wxResult,$uid){
        $cachedValue=$wxResult;
        $cachedValue['uid']=$uid;
        //scope=16代表App用户的权限数值
        $cachedValue['scope']=ScopeEnum::User;//作用域

        //scope=32代表CMS(管理员)用户的权限数值
        // $cachedValue['scope']=32;
        return $cachedValue;
    }

    //openID不存在 则新增一条记录
    private function newUser($openid){
        $user=UserModel::create([
            'openid'=>$openid
        ]);
        return $user->id;
    }

    //封装抛出一个异常
    private function processLoginError($wxResult){
        throw new WeChatException([
            'msg'=>$wxResult['errmsg'],
            'errorCode'=>$wxResult['errcode']
        ]);
        
    }
}